package com.sundablog.spring.framework.webmvc.servlet;


import com.sundablog.spring.framework.annotation.*;
import com.sundablog.spring.framework.context.SDApplicationContext;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.*;

/**
 * @Title:
 * @Package com.sundablog.mvc.V1
 * @Description: TODO
 * @author: 孙达
 * @date: 2020/04/01 17:30
 * @Copyright: All rights Reserved, Designed By www.sundablog.com
 */
public class SDDispatchServlet extends HttpServlet {

    private SDApplicationContext applicationContext;




    private Map<String,Method> handlerMapping = new HashMap<String, Method>();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws  IOException {
        this.doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws  IOException {
        //委派
        try {
            doDispatch(req,resp);
        } catch (Exception e){
            e.printStackTrace();
            resp.getWriter().write("500 exception,Detail");
        }

    }

    private void doDispatch(HttpServletRequest req, HttpServletResponse resp) throws Exception {

        String url = req.getRequestURI();
        String contextPath = req.getContextPath();
        url = url.replaceAll(contextPath,"").replaceAll("/+","/");

        if (!this.handlerMapping.containsKey(url)){
            resp.getWriter().write("404 Not Found!");
            return;
        }

        Map<String,String[]> params = req.getParameterMap();

        Method method = this.handlerMapping.get(url);

        //获取形参列表
        Class<?> [] parameterTypes = method.getParameterTypes();
        Object [] paramValues = new Object[parameterTypes.length];

        for (int i = 0; i < parameterTypes.length; i++) {
            Class paramterType = parameterTypes[i];
            if(paramterType == HttpServletRequest.class){
                paramValues[i] = req;
            }else if(paramterType == HttpServletResponse.class){
                paramValues[i] = resp;
            }else if(paramterType == String.class){
                //通过运行时的状态去拿到你
                Annotation[] [] pa = method.getParameterAnnotations();
                for (int j = 0; j < pa.length ; j ++) {
                    for(Annotation a : pa[i]){
                        if(a instanceof SDRequestParam){
                            String paramName = ((SDRequestParam) a).value();
                            if(!"".equals(paramName.trim())){
                                String value = Arrays.toString(params.get(paramName))
                                        .replaceAll("\\[|\\]","")
                                        .replaceAll("\\s+",",");
                                paramValues[i] = value;
                            }
                        }
                    }
                }

            }
        }



        //暂时硬编码
        String beanName = toLowerFirstCase(method.getDeclaringClass().getSimpleName());
        //赋值实参列表
        method.invoke(applicationContext.getBean(beanName),paramValues);



    }

    @Override
    public void init(ServletConfig config) throws ServletException {

        //初始化 Spring核心Ioc容器
        applicationContext = new SDApplicationContext(config.getInitParameter("contextConfigLocation"));

        doInitHandlerMapping();

        System.out.println("初始化完成");

    }

    private void doInitHandlerMapping() {

        if (this.applicationContext.getBeanDefinitionCount() == 0){
            return;
        }

        for (String beanName : this.applicationContext.getBeanDefinitionNames()) {
            Class<?> clazz = applicationContext.getBean(beanName).getClass();

            //判断是否加了SDController注解
            if (!clazz.isAnnotationPresent(SDController.class)){
                continue;
            }

            //获取class上的URL
            String baseUrl = "";
            if (clazz.isAnnotationPresent(SDRequestMapping.class)){
                SDRequestMapping requestMapping = clazz.getAnnotation(SDRequestMapping.class);
                baseUrl = requestMapping.value();
            }

            //获取所有 public
            for (Method method : clazz.getMethods()) {
                //判断是否加了SDRequestMapping注解
                if (!method.isAnnotationPresent(SDRequestMapping.class)){
                    continue;
                }
                //提前每个方法上的URL
                SDRequestMapping requestMapping = method.getAnnotation(SDRequestMapping.class);
                //使用正则表达式无论有多少个/替换成一个/

                String url = ("/"+baseUrl + "/" + requestMapping.value()).replaceAll("/+","/");
                handlerMapping.put(url,method);
                System.out.println("Mapped : " + url + "," + method);
            }

        }

    }



    /**
     * 首字母小写
     * @param simpleName
     * @return
     */
    private String toLowerFirstCase(String simpleName) {
        char[] chars = simpleName.toCharArray();
        chars[0] += 32;
        return String.valueOf(chars);
    }
}
